﻿using System;
using System.Collections.Generic;
using System.Linq;

using ET;
using Marx;
using Server;

namespace Demo
{
    [ObjectSystem]
    public class ServiceLoaderAwakeSystem : AwakeSystem<ServiceLoader>
    {
        public override void Awake(ServiceLoader self)
        {
            self.Awake();
        }
    }

    [ObjectSystem]
    public class ServiceLoaderUpdateSystem : UpdateSystem<ServiceLoader>
    {
        public override void Update(ServiceLoader self)
        {
            self.Update();
        }
    }

    public class ServiceLoader : Entity, IAppStartup, IAppShutdown, IAwake, IUpdate
    {
        private List<ServiceBase> services_;
        private List<ITick> ticks_;
        private bool ready_;

        public void Awake()
        {
            ready_ = false;
            services_ = new List<ServiceBase>();
            ticks_ = new List<ITick>();

            int zone = this.DomainZone();
            var serviceScenes = StartConfig.Instance.Scenes.Where(i => i.ZoneId == zone && i.Type == ServerSceneType.Service).ToList();

            long currentScene = this.Domain.Id;
            foreach (var config in ServerConfigration.Instance.Services.Items)
            {
                var index = config.Index % serviceScenes.Count;
                if(serviceScenes[index].ID == currentScene)
                {
                    var type = Type.GetType(config.Type);
                    if (type == null)
                    {
                        throw new Exception($"{config.Type} not found");
                    }

                    AddService(type, config.GetID(zone));
                }
            }

            Host.Instance.AddStarter(this);
            Host.Instance.AddShuter(this);
        }

        public void Update()
        {
            if (ready_)
            {
                foreach (var tick in ticks_)
                {
                    tick.Tick();
                }
            }
        }

        public void AddService<T>(long id) where T : ServiceBase, new()
        {
            var service = AddChildWithId<T>(id);
            service.Init();
            services_.Add(service);

            if (service is ITick tick)
            {
                ticks_.Add(tick);
            }
        }

        public void AddService(Type t, long id)
        {
            if (!t.IsSubclassOf(typeof(ServiceBase)))
            {
                throw new Exception($"{t.Name} is not a service");
            }

            var service = AddChildWithIdByType(t, id) as ServiceBase;
            service.Init();
            services_.Add(service);

            if (service is ITick tick)
            {
                ticks_.Add(tick);
            }
        }

        public async ETTask Startup()
        {
            foreach (var service in services_)
            {
                await service.StartService();
                Log.Info($"Service:[{service.GetType().Name}] started...");
            }
            ready_ = true;
        }

        public async ETTask Shutdown()
        {
            foreach (var service in services_)
            {
                await service.StopService();
            }
        }

        public override void Dispose()
        {
            if(IsDisposed)
            {
                return;
            }
            base.Dispose();
            services_.Clear();
        }
    }
}
